from direct.actor.Actor import Actor
from pandac.PandaModules import CollisionSphere
from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import BitMask32
from inventory import *
import time

class PlayerCharacter(object):
    """ Class representing player's character.
    
    Class attribs:
    _directObjectParent - direct object, with which the player interacts
    _inventory - instance of _inventory, class handling all interactions with _inventory
    _actor - 3D representation of the character
    _name - nickname that player chose for himself
    """
    
    _directObjectParent = None
    _inventory = None
    _actor = None
    _name = 'Not yet implemented'
    
    _isJumping = False
    
    def __init__(self, DirectObject):
        """ Init. It sets directObject parent and, basing on it, creates new
            instance of Inventory class. It also calls methods to set actor
            and collisions.
            
            params:
            DirectObject - 'world' which the player interacts with 
        """
        
        
        self._directObjectParent = DirectObject
        self._inventory = Inventory(self._directObjectParent)
        
        self.setUpPlayerActor()
        self.setUpCollisions()
        
        
    def setUpPlayerActor(self):
        """ Method sets up model and animations for player character.
        """
        
        self._actor =  Actor(
                       "models/ralph",
                            { "run":"models/ralph-run"
                             ,"walk":"models/ralph-walk"
                             }
                       )
        
        self._directObjectParent.setPlayerActor(self._actor) 
        
        self._actor.reparentTo(render)
        self._actor.setScale(.2)
        self._actor.setPos(self._directObjectParent.getEnvStartPosition())
    
    
    def setUpCollisions(self):
        """ Method sets up collisions for character. In order to achieve it,
            it interacts directObjectParent
        """
        
        playerGroundRay = CollisionRay()
        playerGroundRay.setOrigin(0,0,1000)
        playerGroundRay.setDirection(0,0,-1)
        
        playerGroundCol = CollisionNode('playerRay')
        playerGroundCol.addSolid(playerGroundRay)
        
        playerGroundCol.setFromCollideMask(BitMask32.bit(0))
        playerGroundCol.setIntoCollideMask(BitMask32.allOff())
        
        dirObjParent = self._directObjectParent
        
        playerGroundColNp = dirObjParent.getPlayerActor().attachNewNode(
            playerGroundCol
        )
        
        dirObjParent.getColTraverser().addCollider(
              playerGroundColNp
            , dirObjParent._playerGroundHandler
        )
        
####### player sphere collider
        playerSphere = CollisionSphere(0, 0, 0, 10)

        
        playerSphereCol = CollisionNode('playerSphere')
        playerSphereCol.addSolid(playerSphere)
#        
        playerSphereCol.setFromCollideMask(BitMask32.bit(0))
        playerSphereCol.setIntoCollideMask(BitMask32.allOff())
        
        dirObjParent = self._directObjectParent
        
        playerSphereColNp = dirObjParent.getPlayerActor().attachNewNode(
            playerSphereCol
        )
        
        
        dirObjParent.getColTraverser().addCollider(
              playerSphereColNp
            , dirObjParent._playerSphereCollisionHandler
        )
        
    def moveActor(self):
        """ Method defines what to do when the actor is supposed to move
        (animations management).
        """
        
        self._actor.loop("run")
        
    def stopActor(self):
        """ Method defines what to do when the actor is supposed to stop
            (animations management)
        """
        
        self._actor.stop()
        self._actor.pose("walk",5)
        
        
    def getInventory(self):
        """ Returns an instance of Inventory.
        """
        
        return self._inventory
    
    def getActor(self):
        """ Returns actor of player character.
        """
        
        return self._actor
    
    def getName(self):
        """ Returns player name.
        """
        
        return self._name
    
    def setName(self, sNewName):
        """ Sets player name.
        """
        
        self._name = sNewName

    def setActor(self, Actor):
        """ Method for setting up player's model.
        
           params:
           Actor - instance of Actor class 
        """
        self._actor = Actor
        
        
    def setName(self, sName):
        """ Method for setting character's _name.
        
            params:
            sName - characer's _name (string)
        """
        
        self._name = sName
        
